package com.basicsys.common.response;

import com.basicsys.common.annotation.diy.ValidationBean;
import com.basicsys.common.exception.LogicException;
import com.basicsys.common.exception.RepeSubmitException;
//import com.taoding.common.annotation.ValidationBean;
//import com.taoding.common.exception.LogicException;
//import com.taoding.common.exception.RepeSubmitException;
//import com.taoding.common.utils.JsonUtil;
import com.basicsys.common.utils.JsonUtil;
import com.basicsys.common.utils.R;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.validation.ConstraintViolation;
import javax.validation.Validation;
import javax.validation.Validator;
import javax.validation.ValidatorFactory;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;

/**
 * 请求和响应处理器，请求代码时进行Bean验证，
 * 控制器响应后将返回的业务对象转换为前台可以识别的结果
 * @author vincent
 *
 */
@Aspect
@Component
public class ResponseInterceptor {

    ValidatorFactory validatorFactory = Validation.buildDefaultValidatorFactory();
    Validator validator = validatorFactory.getValidator();
    
//    private static final Logger logger = LoggerFactory.getLogger(ResponseInterceptor.class);

    // https://blog.csdn.net/yakoo5/article/details/17001381  AspectJ的Execution表达式详解

    //@Around("execution(* com.taoding.controller..*Controller.*(..))")
    //@Around("execution(* com.taoding.controller..*Controller.*(..)) and !execution(* com.taoding.controller.ocr..*Controller.*(..))")
//    @Around("execution(* com.basicsys.modules.sys.controller..*Controller.*(..))  ")
    @Around("execution(* com.basicsys.modules.sys.controller..*SysUserController.*update(..))  ")
    public Object responseHandle(ProceedingJoinPoint pjp) {
        Response response = new Response();
        R res2 = new R();
        String validationResult = validateBean(pjp.getArgs());
        try {
        	if (null != validationResult) {
                res2 = R.error(ResponseCode.INVALID.getValue(), validationResult);
//                response.setMessage(validationResult);
//                response.setResult(null);
//                response.setStatus(ResponseCode.INVALID.getValue());
            } else {
            	Object obj = pjp.proceed();
                Map<String, Object> map = new HashMap<>();
                map.put("code", ResponseCode.OK.getValue());
                map.put("msg", ResponseCode.OK.getDescription());
                map.put("res", obj);
                res2 = R.ok(map);
//                response.setMessage(ResponseCode.OK.getDescription());
//                response.setResult(obj);
//                response.setStatus(ResponseCode.OK.getValue());
            }
        } catch (Throwable throwable) {
//        	ResponseInterceptor.handleException(throwable, response);
        	ResponseInterceptor.handleException(throwable, res2);
        }
        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder
        		.getRequestAttributes()).getRequest();
        HttpServletResponse res = ((ServletRequestAttributes) RequestContextHolder
				.getRequestAttributes()).getResponse();
        if(null!= res){
			res.addHeader("Access-Control-Expose-Headers", "Authorization");
			if (null != request) {
				Enumeration<String> enu=request.getHeaderNames();//取得全部头信息
				while(enu.hasMoreElements()){//以此取出头信息
					String headerName=(String)enu.nextElement();
					if (headerName.equals("accept-sucker")) { //判断请求是不是来自app
					    //这里需要修改
						return JsonUtil.convertResponseToJson(response).replace("null", "\"\"");  //app请求头唯一标识(Accept-sucker:sucker),过滤掉返回json中所有的null值
					}
				}
			}
		}
//        return JsonUtil.convertResponseToJson(response);
//        return JsonUtil.convertResponseToJson(res2);
        return res2;
    }

    /**
     * 查看参数列表中的参数是否需要bean校验，如果需要，则进行校验，并返回错误信息
     * @param objects 参数列表
     * @return null表示较验正常，否则返回第一个校验的错误
     */
    @SuppressWarnings("rawtypes")
    private String validateBean(Object[] objects) {
        if (null == objects || objects.length == 0){
            return null;
        }

        String message = null;

        for (Object obj : objects) {
        	if(null == obj){
        		continue;
        	}

            //遍历参数列表，查看参数是否被com.taoding.common.annotation.ValidationBean声明，
            //如果是，说明该参数需要bean校验
            int length = obj.getClass().getAnnotationsByType(ValidationBean.class).length;
            if (length > 0) {
                Set<ConstraintViolation<Object>> validateResults = validator.validate(obj);
                if (!validateResults.isEmpty()) {
                    for(ConstraintViolation result: validateResults) {
                        message = result.getMessage();
                        break;
                    }
                }
            }
        }
        return message;
    }

    /**
     * 处理异常
     * @param throwable 异常
     * @param response 结果
     */
    public static void handleException(Throwable throwable, Response response) {
    	throwable.printStackTrace();
        if (throwable.getClass().equals(LogicException.class)) {
        	response.setMessage(((LogicException)throwable).getMessageInfo());
        	response.setResult("");
            response.setStatus(ResponseCode.LOGIC_EXCEPTION.getValue());
        } else if (throwable.getClass().equals(RepeSubmitException.class)) {
            response.setMessage(ResponseCode.REPEATED_SUBMIT_EXCEPTION.getDescription());
            response.setResult("");
            response.setStatus(ResponseCode.REPEATED_SUBMIT_EXCEPTION.getValue());
        } else {
        	response.setMessage(ResponseCode.ERROR.getDescription());
        	response.setResult("");
            response.setStatus(ResponseCode.ERROR.getValue());
        }
    }
    public static void handleException(Throwable throwable, R response) {
    	throwable.printStackTrace();
        if (throwable.getClass().equals(LogicException.class)) {
            R.error(ResponseCode.LOGIC_EXCEPTION.getValue(), ((LogicException)throwable).getMessageInfo());
//        	response.setMessage(((LogicException)throwable).getMessageInfo());
//        	response.setResult("");
//            response.setStatus(ResponseCode.LOGIC_EXCEPTION.getValue());
        } else if (throwable.getClass().equals(RepeSubmitException.class)) {
            R.error(ResponseCode.REPEATED_SUBMIT_EXCEPTION.getValue(), ResponseCode.REPEATED_SUBMIT_EXCEPTION.getDescription());

//            response.setMessage(ResponseCode.REPEATED_SUBMIT_EXCEPTION.getDescription());
//            response.setResult("");
//            response.setStatus(ResponseCode.REPEATED_SUBMIT_EXCEPTION.getValue());
        } else {
            R.error(ResponseCode.ERROR.getValue(), ResponseCode.ERROR.getDescription());
//            response.setMessage(ResponseCode.ERROR.getDescription());
//        	response.setResult("");
//            response.setStatus(ResponseCode.ERROR.getValue());
        }
    }
}
